home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / pt20pc.zip / UNDOREDO.C < prev    next >
C/C++ Source or Header  |  1991-02-04  |  8KB  |  287 lines

  1. #include "pt.h"
  2.  
  3. void pascal
  4. /* XTAG:initChanges */
  5. initChanges()
  6. {
  7.     extern struct changeItem *change;
  8.     extern struct changeItem scrapBuffer;
  9.     extern int tailChange, nextChange;
  10.  
  11.     register int i;
  12.     
  13.     for(i = 0; i < NHISTORY; i++) {
  14.         change[i].type = CNULL;
  15.         change[i].firstPiece = NULL;
  16.     }
  17.     tailChange = nextChange = 0;
  18.     scrapBuffer.firstPiece = getFreePiece();
  19.     scrapBuffer.firstPiece->file = ADDFILE;
  20.     scrapBuffer.firstPiece->position = 0L;
  21.     scrapBuffer.firstPiece->length = 0L;
  22. }
  23.  
  24. void pascal
  25. /* XTAG:IncrementNextChange */
  26. IncrementNextChange()
  27. {
  28.     extern int tailChange, nextChange;
  29.     extern struct changeItem *change;
  30.  
  31.     /* change history is a circular buffer */
  32.     if( ++nextChange >= NHISTORY )
  33.         nextChange = 0;
  34.     /* is the change buffer full? */
  35.     if( nextChange == tailChange ) {
  36.         /* if so, free the 'tailChange' change */
  37.         if( change[tailChange].type != CNULL )
  38.             freePieces( change[tailChange].firstPiece );
  39.         change[tailChange].firstPiece = NULL;
  40.         /* and move the 'tail' up one */
  41.         if( ++tailChange >= NHISTORY )
  42.             tailChange = 0;
  43.     }
  44. }
  45.  
  46. void pascal
  47. /* XTAG:redo */
  48. redo()
  49. {
  50.     extern unsigned char msgBuffer[];
  51.     extern struct window *selWindow;
  52.     extern long selBegin, selEnd;
  53.     extern struct changeItem *change;
  54.     extern int tailChange, nextChange;
  55.     extern struct openFile *files;
  56.     extern unsigned char *userMessages[];
  57.  
  58.     register struct changeItem *newChange;
  59.     struct changeItem *thisChange, *prevChange;
  60.     int n, type, count;
  61.  
  62.     /* check if this is a readOnly file */
  63.     if( files[selWindow->fileId].readOnly ) {
  64.         sprintf(msgBuffer, userMessages[READONLYFILE],
  65.             files[selWindow->fileId].origName);
  66.         msg(msgBuffer, 1);
  67.         return;
  68.     }
  69.  
  70.     if( nextChange == tailChange ) {
  71. noChanges:
  72.         msg("No previous change to redo", 2);
  73.         return;
  74.     }
  75.  
  76.     n = nextChange;    /* remember where the next change is */
  77.     
  78.     /* find the change to redo (not a delete ) */
  79.     count = 0;
  80.     while( 1 ) {
  81.         thisChange = &change[n];
  82.         if((thisChange->type)!=CDELETE && (thisChange->type)!=CNULL)
  83.             break;
  84.         if( --n < 0 )
  85.             n = NHISTORY - 1;
  86.         if( count++ > NHISTORY )
  87.             goto noChanges;
  88.     }
  89.  
  90.     switch( thisChange->type ) {
  91.  
  92.     case CINSERT:
  93.         type = CINSERT;
  94.         goto doCopy;
  95.  
  96.     case CCOPY:
  97.     case CMOVE:
  98.         type = CCOPY;
  99.     doCopy:
  100.         /* see if the previous change was a delete */
  101.         if( --n < 0 )
  102.             n = NHISTORY - 1;
  103.         prevChange = &change[n];
  104.         if( thisChange->position == prevChange->position 
  105.          && prevChange->type == CDELETE )
  106.             /* the delete must go into the history first */
  107.             deleteChars(selWindow->fileId, NOUPDATE, 0);
  108.         /* find the slot to record this change */
  109.         IncrementNextChange();
  110.         /* record the change before copyPieces changes things */
  111.         newChange = &change[nextChange];
  112.         newChange->type = type;
  113.         newChange->position = selBegin;
  114.         newChange->length = thisChange->length;
  115.         newChange->fileId = selWindow->fileId;
  116.         newChange->firstPiece = dupPieces(thisChange->firstPiece);
  117.         copyPieces(thisChange->firstPiece, selWindow, selBegin,
  118.             thisChange->length, 1);
  119.         break;
  120.     
  121.     case CDELETE:
  122.         deleteChars(selWindow->fileId, UPDATEWINDOWS, 0);
  123.         break;
  124.     }
  125. }
  126.  
  127. void pascal
  128. /* XTAG:undo */
  129. undo(doHistory)
  130.     int doHistory;
  131. {
  132.     extern unsigned char msgBuffer[];
  133.     extern struct window *selWindow;
  134.     extern long selBegin, selEnd;
  135.     extern struct window *windowList;
  136.     extern struct changeItem *change;
  137.     extern int tailChange, nextChange;
  138.     extern int debug;
  139.  
  140.     int n, delAlso, count;
  141.     register struct changeItem *newChange;
  142.     struct changeItem *thisChange, *prevChange;
  143.     struct window *w1;
  144.  
  145.     if( nextChange == tailChange ) {
  146. noChanges:
  147.         msg("No previous change to undo", 2);
  148.         return;
  149.     }
  150.  
  151.     /* find the change to undo */
  152.     n = nextChange;
  153.     count = 0;
  154.     while( 1 ) {
  155.         thisChange = &change[n];
  156.         if( (thisChange->type) != CNULL )
  157.             break;
  158.         if( --n < 0 )
  159.             n = NHISTORY - 1;
  160.         if( count++ > NHISTORY )
  161.             goto noChanges;
  162.     }
  163.     nextChange = n;
  164.     if( --n < 0 )
  165.         n = NHISTORY - 1;
  166.     prevChange = &change[n];
  167.  
  168.     /* find a window displaying the file the change was made in */
  169.     if( thisChange->fileId != selWindow->fileId ) {
  170.         w1 = windowList;
  171.         while( w1 != NULL && w1->fileId != thisChange->fileId )
  172.             w1 = w1->nextWindow;
  173.         if( w1 == NULL ) {
  174.             msg("Cannot undo. No windows have that file open.",3);
  175.             return;
  176.         } else
  177.             selWindow = w1;
  178.     }
  179.     
  180.     switch( thisChange->type ) {
  181.  
  182.     case CDELETE:
  183.         if( doHistory ) {
  184.             /* find the slot to record this change */
  185.             IncrementNextChange();
  186.             newChange = &change[nextChange];
  187.             newChange->type = CCOPY;
  188.             newChange->position = thisChange->position;
  189.             newChange->length = thisChange->length;
  190.             newChange->fileId = selWindow->fileId;
  191.             newChange->firstPiece =
  192.                 dupPieces(thisChange->firstPiece);
  193.         }
  194.         showChange();
  195.         copyPieces(thisChange->firstPiece, selWindow,
  196.             thisChange->position, thisChange->length, 1);
  197.         if( !doHistory ) {
  198.             change[nextChange--].type = CNULL;
  199.             if( nextChange < 0 )
  200.                 nextChange = NHISTORY - 1;
  201.         }
  202.         /* see if this is really the DELETE of a CMOVE */
  203.         if( prevChange->type != CMOVE )
  204.             break;
  205.         if( doHistory )        /* if we are recording in history */
  206.             newChange->type = CMOVE; /* change it to a move */
  207.         /* else finish undoing the move by dropping through */
  208.         /* to the CCOPY case to delete the MOVEd text */
  209.         thisChange = prevChange;
  210.         /* erase this change from the history list */
  211.  
  212.     case CCOPY:
  213.         selBegin = thisChange->position;
  214.         selEnd = selBegin + thisChange->length - 1;
  215.         showChange();
  216.         deleteChars(thisChange->fileId, UPDATEWINDOWS,
  217.             doHistory ? 0 : 2);
  218.         /* erase this change from the history list */
  219.         if( !doHistory ) {
  220.             change[nextChange--].type = CNULL;
  221.             if( nextChange < 0 )
  222.                 nextChange = NHISTORY - 1;
  223.         }
  224.         break;
  225.  
  226.     case CINSERT:
  227.         /* delete the characters inserted */
  228.         selBegin = thisChange->position;
  229.         selEnd = selBegin + thisChange->length - 1;
  230.         /* test this first so we can avoid updating the */
  231.         /* screen twice once for the delete and again for */
  232.         /* the copy to follow */
  233.         if( thisChange->position == prevChange->position 
  234.          && prevChange->type == CDELETE )
  235.             delAlso = NOUPDATE;
  236.         else
  237.             delAlso = UPDATEWINDOWS;
  238.         showChange();
  239.         deleteChars(thisChange->fileId, delAlso,
  240.             doHistory ? 0 : 2);
  241.         /* erase this change from the history list */
  242.         if( !doHistory ) {
  243.             /* erase the last 1 or 2 changes */
  244.             change[nextChange--].type = CNULL;
  245.             if( delAlso == NOUPDATE ) {
  246.                 change[nextChange--].type = CNULL;
  247.             }
  248.             if( nextChange < 0 )
  249.                 nextChange = NHISTORY - 1;
  250.         }
  251.         /* see if there is a previous, related delete to undo */
  252.         if( delAlso == NOUPDATE ) {
  253.             if( doHistory ) {
  254.                 /* find the slot to record this change */
  255.                 IncrementNextChange();
  256.                 newChange = &change[nextChange];
  257.                 newChange->type = CINSERT;
  258.                 newChange->position = selBegin;
  259.                 newChange->length = prevChange->length;
  260.                 newChange->fileId = prevChange->fileId;
  261.                 newChange->firstPiece =
  262.                     dupPieces(prevChange->firstPiece);
  263.             }
  264.             copyPieces(prevChange->firstPiece, selWindow,
  265.                 selBegin, prevChange->length, 1);
  266.         }
  267.         break;
  268.     }
  269. }
  270.  
  271. /* make sure the change is visible */
  272. void pascal
  273. /* XTAG:showChange */
  274. showChange()
  275. {
  276.     extern long selBegin, selEnd;
  277.     extern struct window *selWindow;
  278.     extern struct window *windowList;
  279.     
  280.     /* if the selection window is not on top */
  281.     /* or if the selection is not in the window */
  282.     /* then move the window to show the selection */
  283.     if( windowList != selWindow || selBegin < selWindow->posTopline
  284.      || selEnd > selWindow->posBotline )
  285.          doGoSel(selWindow);
  286. }
  287.